package com.sybil.spa.servicio;

import com.sybil.spa.dao.ReembolsoDAO;
import com.sybil.spa.dominio.DetalleReembolso;
import com.sybil.spa.dominio.Flujo;
import com.sybil.spa.dominio.Reembolso;
import com.sybil.spa.dominio.Solicitud;
import com.sybil.spa.dominio.Usuario;
import com.sybil.spa.dominio.r12.ConceptoGasto;
import com.sybil.spa.dominio.r12.Impuesto;
import com.sybil.spa.dominio.r12.Moneda;
import com.sybil.spa.dominio.r12.Proveedor;
import com.sybil.spa.dominio.r12.TipoComprobante;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("reembolsoServicio")
@Transactional(readOnly = true)
public class ReembolsoServicio {

   @Autowired
   private ReembolsoDAO reembolsoDAO;
   @Autowired
   private SolicitudServicio solicitudServicio;
   @Autowired
   private CatalogosR12Servicio catalogosR12Servicio;

   public void guardar(Reembolso reembolso, boolean enviar) {
      Integer secuencia = reembolsoDAO.getSecuencia();
      reembolso.setNumero(secuencia);
      reembolso.setEstatus("R");
      reembolso.setFecha(new Date());
      List<DetalleReembolso> detalles = reembolso.getDetalles();
      double monto = 0;
      if (detalles != null) {
         for (DetalleReembolso detalle : detalles) {
            detalle.setUsuarioCreo(reembolso.getUsuarioCreo());
            detalle.getLlave().setNumeroReembolso(reembolso.getNumero());
            monto += detalle.getMontoSinIva() + detalle.getMontoIva() + detalle.getMontoPropina() + detalle.getMontoOtroImpuesto();
            detalle.setSumaSinIva(detalle.getMontoSinIva() + detalle.getMontoPropina() + detalle.getMontoOtroImpuesto());
         }
      }
      reembolso.setMontoFavorUsuario(monto);
      if (enviar) {
         Solicitud solicitud = solicitudServicio.generarSolicitud(
                 reembolso.getSolicitud().getFlujo().getClave(),
                 reembolso.getUsuarioCreo(), monto, reembolso.getDescripcion());
         solicitudServicio.guardar(solicitud);
         reembolso.setEstatus("P");
         reembolso.setSolicitud(solicitud);
         try {
            reembolsoDAO.guardarReembolso(reembolso);
         } catch (Exception e) {
            solicitudServicio.eliminarSolicitud(solicitud.getLlave().getClaveFlujo(), solicitud.getLlave().getNumeroSolicitud());
         }
      } else {
         reembolso.setSolicitud(null);
         reembolsoDAO.guardarReembolso(reembolso);
      }
   }

   public void editar(Reembolso reembolso, boolean enviar) {
      Reembolso _reembolso = reembolsoDAO.getReembolso(reembolso.getNumero());
      List<DetalleReembolso> detalles = reembolso.getDetalles();
      double monto = 0;
      if (detalles == null || detalles.isEmpty()) {
         reembolso.setDetalles(null);
      } else {
         for (DetalleReembolso detalle : detalles) {
            detalle.getLlave().setNumeroReembolso(reembolso.getNumero());
            detalle.setUsuarioModif(reembolso.getUsuarioModif());
            monto += detalle.getMontoSinIva() + detalle.getMontoIva() + detalle.getMontoPropina() + detalle.getMontoOtroImpuesto();
            detalle.setSumaSinIva(detalle.getMontoSinIva() + detalle.getMontoPropina() + detalle.getMontoOtroImpuesto());
         }
      }
      if (reembolso.getAnticipos() == null || reembolso.getAnticipos().isEmpty()) {
         reembolso.setAnticipos(null);
      }
      reembolso.setFecha(_reembolso.getFecha());
      reembolso.setMontoFavorUsuario(monto);
      Solicitud solicitud = _reembolso.getSolicitud();
      if (enviar) {
         if (solicitud == null) {
            solicitud = solicitudServicio.generarSolicitud(
                    reembolso.getSolicitud().getFlujo().getClave(),
                    reembolso.getUsuarioCreo(), monto, reembolso.getDescripcion());
            solicitudServicio.guardar(solicitud);
            reembolso.setSolicitud(solicitud);
            try {
               reembolso.setEstatus("P");
               reembolsoDAO.editarReembolso(reembolso);
            } catch (Exception e) {
               solicitudServicio.eliminarSolicitud(solicitud.getLlave().getClaveFlujo(), solicitud.getLlave().getNumeroSolicitud());
            }
         } else { //suponiendo que solo se puede editar una solicitud en el paso inicial.
            solicitud = solicitudServicio.aprobarSolicitud(solicitud.getLlave().getClaveFlujo(),
                    solicitud.getLlave().getNumeroSolicitud(), reembolso.getUsuarioModif(),
                    solicitud.getPaso().getEventos().get(0).getLlave().getClaveEvento(), reembolso.getDescripcion());
            reembolso.setSolicitud(solicitud);
            solicitudServicio.editar(solicitud);
         }
         if ("R".equals(reembolso.getEstatus()) || "C".equals(reembolso.getEstatus())) {
            reembolso.setEstatus("P");
         }
         reembolsoDAO.editarReembolso(reembolso);
      } else {
         reembolso.setSolicitud(solicitud);
         reembolsoDAO.editarReembolso(reembolso);
      }
   }

   @Transactional(readOnly = false)
   public void eliminar(Integer numero) {
      Reembolso reembolso = reembolsoDAO.getReembolso(numero);
      reembolsoDAO.eliminarReembolso(reembolso);
   }

   public List<Reembolso> obtenerReembolsos() {
      return reembolsoDAO.getReembolsos(false);
   }

   public Reembolso obtenerReembolso(Integer numero) {
      Reembolso reembolso = reembolsoDAO.getReembolso(numero);
      List<DetalleReembolso> detalles = reembolso.getDetalles();
      for (DetalleReembolso detalle : detalles) {
         detalle.setConceptoGasto(catalogosR12Servicio.obtenerConceptoGasto(detalle.getNumeroConceptoGasto()));
         detalle.setTipoComprobante(catalogosR12Servicio.obtenerTipoComprobante(detalle.getClaveTipoComprobante()));
//         detalle.setMoneda(catalogosR12Servicio.obtenerMoneda(detalle.getClaveMoneda()));
      }
      return reembolso;
   }

   public List<Reembolso> obtenerReembolsos(String fechaDesde, String fechaHasta, String estatus, String numeroReembolso) {
      int numero;
      final DateFormat soloFecha = new SimpleDateFormat("dd/MM/yyyy");
      Date fecha1, fecha2;
      try {
         fecha1 = soloFecha.parse(fechaDesde);
         fecha2 = soloFecha.parse(fechaHasta);
         long fin = fecha2.getTime();
         fin += 82800000 + 3540000 + 59000;//se se agregan 23 horas 59 min, 59 seg
         fecha2.setTime(fin);
      } catch (ParseException ex) {
         fecha1 = null;
         fecha2 = null;
      }
      try {
         numero = Integer.parseInt(numeroReembolso);
      } catch (NumberFormatException ex) {
         numero = 0;
      }
      List<Reembolso> reembolsos = reembolsoDAO.getReembolsos(fecha1, fecha2,
              estatus, numero);
      for (Reembolso reembolso : reembolsos) {
         reembolso.setUsuario(solicitudServicio.getUsuario(reembolso.getClaveUsuario()));
      }
      return reembolsos;
   }

   public void aprobar(String claveFlujo, int numeroSolicitud, String claveUsuario, String claveEvento, String comentarios) {
      Solicitud solicitud = solicitudServicio.aprobarSolicitud(claveFlujo, numeroSolicitud, claveUsuario, claveEvento, comentarios);
      if (solicitud != null) {
         Reembolso reembolso = solicitud.getReembolso();
         if (reembolso != null) {
            if ("S".equals(solicitud.getTerminado())) {
               if ("S".equals(solicitud.getFinalCorrecto())) {
                  reembolso.setEstatus("A");
               } else {
                  reembolso.setEstatus("X");
               }
            } else if ("I".equals(solicitud.getPaso().getTipo())) {
               reembolso.setEstatus("C");
            }
            if (reembolso.getDetalles() == null || reembolso.getDetalles().isEmpty()) {
               reembolso.setDetalles(null);
            }
            if (reembolso.getAnticipos() == null || reembolso.getAnticipos().isEmpty()) {
               reembolso.setAnticipos(null);
            }
            reembolsoDAO.editarReembolso(reembolso);
            solicitudServicio.editar(solicitud);
         }
      } else {
         //error en el solicitud
      }
   }

   public Solicitud obtenerSolicitud(String claveFlujo, int numeroSolicitud) {
      Solicitud solicitud = solicitudServicio.obtenerSolicitud(claveFlujo, numeroSolicitud);
      List<DetalleReembolso> detalles = solicitud.getReembolso().getDetalles();
      for (DetalleReembolso detalle : detalles) {
         detalle.setConceptoGasto(catalogosR12Servicio.obtenerConceptoGasto(detalle.getNumeroConceptoGasto()));
         detalle.setTipoComprobante(catalogosR12Servicio.obtenerTipoComprobante(detalle.getClaveTipoComprobante()));
         detalle.setMoneda(catalogosR12Servicio.obtenerMoneda(detalle.getClaveMoneda()));
      }
      return solicitud;
   }

   public Usuario getUsuario(String usuarioActual) {
      return solicitudServicio.getUsuario(usuarioActual);
   }

   public List<Flujo> obtenerFlujos(String usuarioActual) {
      return solicitudServicio.getFlujo(usuarioActual, "RE");
   }

   public List<ConceptoGasto> obtenerConceptosGasto() {
      return catalogosR12Servicio.obtenerConceptosGasto();
   }

   public List<TipoComprobante> obtenerTiposComprobante() {
      return catalogosR12Servicio.obtenerTiposComprobante();
   }

   public List<Moneda> obtenerMonedas() {
      return catalogosR12Servicio.obtenerMonedas();
   }

   public List<Proveedor> obtenerProveedores() {
      return catalogosR12Servicio.obtenerProveedores();
   }

   public List<Impuesto> obtenerImpuestos() {
      return catalogosR12Servicio.obtenerImpuestos();
   }

   public Proveedor obtenerProveedor(int numeroProveedor) {
      return catalogosR12Servicio.obtenerProveedor(numeroProveedor);
   }
}
